# -*- coding: utf-8 -*-
"""
NumPy 从基础到高级的完整示例

本文件包含从浅入深的NumPy使用示例，涵盖基础操作到高级应用，
包括真实数据集的处理和分析。
"""

import numpy as np
import matplotlib.pyplot as plt
from typing import Tuple, List
import time

# ============================================================================
# 第一部分：基础操作 (Beginner Level)
# ============================================================================

def basic_array_operations():
    """基础数组操作示例"""
    print("=" * 60)
    print("第一部分：基础数组操作")
    print("=" * 60)
    
    # 1.1 创建数组的多种方式
    print("\n1.1 创建数组的多种方式:")
    
    # 从列表创建
    arr1 = np.array([1, 2, 3, 4, 5])
    print(f"从列表创建: {arr1}")
    
    # 创建特殊数组
    zeros = np.zeros(5)
    ones = np.ones((2, 3))
    identity = np.eye(3)  # 单位矩阵
    random_arr = np.random.random((2, 2))
    
    print(f"全零数组: {zeros}")
    print(f"全一数组:\n{ones}")
    print(f"单位矩阵:\n{identity}")
    print(f"随机数组:\n{random_arr}")
    
    # 1.2 数组属性
    print("\n1.2 数组属性:")
    arr2d = np.array([[1, 2, 3], [4, 5, 6]])
    print(f"数组形状: {arr2d.shape}")
    print(f"数组维度: {arr2d.ndim}")
    print(f"数组大小: {arr2d.size}")
    print(f"数据类型: {arr2d.dtype}")
    
    # 1.3 基本运算
    print("\n1.3 基本运算:")
    a = np.array([1, 2, 3])
    b = np.array([4, 5, 6])
    
    print(f"a = {a}, b = {b}")
    print(f"加法: a + b = {a + b}")
    print(f"减法: a - b = {a - b}")
    print(f"乘法: a * b = {a * b}")
    print(f"除法: a / b = {a / b}")
    print(f"幂运算: a ** 2 = {a ** 2}")

# ============================================================================
# 第二部分：中级操作 (Intermediate Level)
# ============================================================================

def intermediate_operations():
    """中级操作示例"""
    print("\n" + "=" * 60)
    print("第二部分：中级操作")
    print("=" * 60)
    
    # 2.1 高级索引和切片
    print("\n2.1 高级索引和切片:")
    arr = np.arange(20).reshape(4, 5)
    print(f"原数组:\n{arr}")
    
    # 布尔索引
    mask = arr > 10
    print(f"大于10的元素: {arr[mask]}")
    
    # 花式索引
    indices = [0, 2, 3]
    print(f"选择第0,2,3行:\n{arr[indices]}")
    
    # 2.2 数组变形和连接
    print("\n2.2 数组变形和连接:")
    arr1 = np.arange(12).reshape(3, 4)
    arr2 = np.arange(12, 24).reshape(3, 4)
    
    print(f"数组1:\n{arr1}")
    print(f"数组2:\n{arr2}")
    
    # 垂直连接
    v_concat = np.vstack((arr1, arr2))
    print(f"垂直连接:\n{v_concat}")
    
    # 水平连接
    h_concat = np.hstack((arr1, arr2))
    print(f"水平连接:\n{h_concat}")
    
    # 2.3 统计和聚合函数
    print("\n2.3 统计和聚合函数:")
    data = np.random.normal(100, 15, 1000)  # 正态分布数据
    
    print(f"数据样本 (前10个): {data[:10]}")
    print(f"平均值: {np.mean(data):.2f}")
    print(f"标准差: {np.std(data):.2f}")
    print(f"最小值: {np.min(data):.2f}")
    print(f"最大值: {np.max(data):.2f}")
    print(f"中位数: {np.median(data):.2f}")
    print(f"25%分位数: {np.percentile(data, 25):.2f}")
    print(f"75%分位数: {np.percentile(data, 75):.2f}")

# ============================================================================
# 第三部分：高级操作 (Advanced Level)
# ============================================================================

def advanced_operations():
    """高级操作示例"""
    print("\n" + "=" * 60)
    print("第三部分：高级操作")
    print("=" * 60)
    
    # 3.1 线性代数操作
    print("\n3.1 线性代数操作:")
    
    # 矩阵运算
    A = np.random.randint(1, 10, (3, 3))
    B = np.random.randint(1, 10, (3, 3))
    
    print(f"矩阵A:\n{A}")
    print(f"矩阵B:\n{B}")
    
    # 矩阵乘法
    C = np.dot(A, B)
    print(f"矩阵乘法 A·B:\n{C}")
    
    # 矩阵的逆
    try:
        A_inv = np.linalg.inv(A)
        print(f"矩阵A的逆:\n{A_inv}")
        
        # 验证 A * A^(-1) = I
        identity_check = np.dot(A, A_inv)
        print(f"验证 A·A^(-1):\n{identity_check}")
    except np.linalg.LinAlgError:
        print("矩阵A不可逆")
    
    # 特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(A)
    print(f"特征值: {eigenvalues}")
    print(f"特征向量:\n{eigenvectors}")
    
    # 3.2 广播机制
    print("\n3.2 广播机制:")
    
    # 不同形状数组的运算
    arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
    arr_1d = np.array([10, 20, 30])
    
    print(f"2D数组:\n{arr_2d}")
    print(f"1D数组: {arr_1d}")
    print(f"广播相加:\n{arr_2d + arr_1d}")
    
    # 3.3 向量化函数
    print("\n3.3 向量化函数:")
    
    def custom_function(x):
        """自定义函数"""
        if x > 0:
            return np.sqrt(x)
        else:
            return 0
    
    # 向量化函数
    vectorized_func = np.vectorize(custom_function)
    
    test_array = np.array([-2, -1, 0, 1, 4, 9, 16])
    result = vectorized_func(test_array)
    
    print(f"输入数组: {test_array}")
    print(f"向量化函数结果: {result}")

# ============================================================================
# 第四部分：真实数据集应用 (Real-world Applications)
# ============================================================================

def real_world_applications():
    """真实数据集应用示例"""
    print("\n" + "=" * 60)
    print("第四部分：真实数据集应用")
    print("=" * 60)
    
    # 4.1 模拟股票价格数据分析
    print("\n4.1 股票价格数据分析:")
    
    # 生成模拟股票价格数据
    np.random.seed(42)  # 确保结果可重现
    days = 252  # 一年的交易日
    initial_price = 100
    
    # 使用随机游走模型生成价格
    daily_returns = np.random.normal(0.001, 0.02, days)  # 日收益率
    prices = [initial_price]
    
    for return_rate in daily_returns:
        new_price = prices[-1] * (1 + return_rate)
        prices.append(new_price)
    
    prices = np.array(prices[1:])  # 移除初始价格
    
    print(f"股票价格统计:")
    print(f"  起始价格: ${initial_price:.2f}")
    print(f"  结束价格: ${prices[-1]:.2f}")
    print(f"  最高价格: ${np.max(prices):.2f}")
    print(f"  最低价格: ${np.min(prices):.2f}")
    print(f"  平均价格: ${np.mean(prices):.2f}")
    print(f"  价格波动率: {np.std(prices):.2f}")
    
    # 计算移动平均线
    def moving_average(data, window):
        """计算移动平均线"""
        return np.convolve(data, np.ones(window)/window, mode='valid')
    
    ma_20 = moving_average(prices, 20)
    ma_50 = moving_average(prices, 50)
    
    print(f"\n移动平均线分析:")
    print(f"  20日均线最新值: ${ma_20[-1]:.2f}")
    print(f"  50日均线最新值: ${ma_50[-1]:.2f}")
    
    # 4.2 图像处理示例
    print("\n4.2 图像处理示例:")
    
    # 创建一个简单的"图像"（2D数组）
    image = np.random.randint(0, 256, (100, 100), dtype=np.uint8)
    
    print(f"原始图像形状: {image.shape}")
    print(f"像素值范围: {np.min(image)} - {np.max(image)}")
    
    # 图像滤波（简单的均值滤波）
    def simple_blur(img, kernel_size=3):
        """简单的均值滤波"""
        pad_size = kernel_size // 2
        padded_img = np.pad(img, pad_size, mode='edge')
        blurred = np.zeros_like(img)
        
        for i in range(img.shape[0]):
            for j in range(img.shape[1]):
                blurred[i, j] = np.mean(
                    padded_img[i:i+kernel_size, j:j+kernel_size]
                )
        
        return blurred.astype(np.uint8)
    
    blurred_image = simple_blur(image)
    
    print(f"滤波后图像形状: {blurred_image.shape}")
    print(f"滤波后像素值范围: {np.min(blurred_image)} - {np.max(blurred_image)}")
    
    # 4.3 科学计算示例：数值积分
    print("\n4.3 数值积分示例:")
    
    def numerical_integration_example():
        """使用梯形法则进行数值积分"""
        # 计算 ∫[0,π] sin(x) dx 的近似值（真实值为2）
        
        def f(x):
            return np.sin(x)
        
        # 不同精度的积分
        for n in [10, 100, 1000]:
            x = np.linspace(0, np.pi, n+1)
            y = f(x)
            
            # 梯形法则
            integral = np.trapz(y, x)
            error = abs(integral - 2.0)
            
            print(f"  n={n:4d}: 积分值={integral:.6f}, 误差={error:.6f}")
    
    numerical_integration_example()

# ============================================================================
# 第五部分：性能优化和最佳实践 (Performance & Best Practices)
# ============================================================================

def performance_and_best_practices():
    """性能优化和最佳实践"""
    print("\n" + "=" * 60)
    print("第五部分：性能优化和最佳实践")
    print("=" * 60)
    
    # 5.1 向量化 vs 循环性能比较
    print("\n5.1 向量化 vs 循环性能比较:")
    
    size = 1000000
    arr1 = np.random.random(size)
    arr2 = np.random.random(size)
    
    # 使用循环的方法
    start_time = time.time()
    result_loop = []
    for i in range(len(arr1)):
        result_loop.append(arr1[i] * arr2[i])
    loop_time = time.time() - start_time
    
    # 使用向量化的方法
    start_time = time.time()
    result_vectorized = arr1 * arr2
    vectorized_time = time.time() - start_time
    
    print(f"数组大小: {size:,}")
    print(f"循环方法耗时: {loop_time:.4f} 秒")
    print(f"向量化方法耗时: {vectorized_time:.4f} 秒")
    print(f"性能提升: {loop_time/vectorized_time:.1f}x")
    
    # 5.2 内存使用优化
    print("\n5.2 内存使用优化:")
    
    # 使用合适的数据类型
    large_array_float64 = np.ones(1000000, dtype=np.float64)
    large_array_float32 = np.ones(1000000, dtype=np.float32)
    large_array_int32 = np.ones(1000000, dtype=np.int32)
    
    print(f"float64数组内存使用: {large_array_float64.nbytes / 1024 / 1024:.2f} MB")
    print(f"float32数组内存使用: {large_array_float32.nbytes / 1024 / 1024:.2f} MB")
    print(f"int32数组内存使用: {large_array_int32.nbytes / 1024 / 1024:.2f} MB")
    
    # 5.3 常用技巧和陷阱
    print("\n5.3 常用技巧和陷阱:")
    
    # 技巧1：使用视图而不是副本
    original = np.arange(10)
    view = original[::2]  # 这是一个视图
    copy = original[::2].copy()  # 这是一个副本
    
    print(f"原数组: {original}")
    print(f"视图: {view}")
    
    # 修改原数组
    original[0] = 999
    print(f"修改原数组后:")
    print(f"  原数组: {original}")
    print(f"  视图: {view}")
    print(f"  副本: {copy}")
    
    # 技巧2：使用布尔索引进行条件操作
    data = np.array([1, -2, 3, -4, 5, -6])
    print(f"\n原数据: {data}")
    
    # 将负数替换为0
    data_cleaned = np.where(data < 0, 0, data)
    print(f"清理后: {data_cleaned}")

def run_all_examples():
    """运行所有示例"""
    print("NumPy 从基础到高级完整示例")
    print("=" * 80)
    
    basic_array_operations()
    intermediate_operations()
    advanced_operations()
    real_world_applications()
    performance_and_best_practices()
    
    print("\n" + "=" * 80)
    print("所有示例运行完成！")
    print("=" * 80)

def run_tests():
    """运行测试"""
    print("\n" + "=" * 60)
    print("运行测试")
    print("=" * 60)
    
    # 测试基础操作
    arr = np.array([1, 2, 3])
    assert arr.shape == (3,), "基础数组创建测试失败"
    
    # 测试运算
    result = arr + np.array([4, 5, 6])
    expected = np.array([5, 7, 9])
    assert np.array_equal(result, expected), "数组运算测试失败"
    
    # 测试统计函数
    assert np.mean([1, 2, 3, 4, 5]) == 3.0, "统计函数测试失败"
    
    # 测试线性代数
    A = np.array([[1, 2], [3, 4]])
    B = np.array([[5, 6], [7, 8]])
    C = np.dot(A, B)
    expected_C = np.array([[19, 22], [43, 50]])
    assert np.array_equal(C, expected_C), "矩阵乘法测试失败"
    
    # 测试广播
    arr_2d = np.array([[1, 2], [3, 4]])
    arr_1d = np.array([10, 20])
    result = arr_2d + arr_1d
    expected = np.array([[11, 22], [13, 24]])
    assert np.array_equal(result, expected), "广播测试失败"
    
    print("✅ 所有测试通过！")

if __name__ == "__main__":
    run_all_examples()
    run_tests()